/* Copyright (C) 2010 Luca Piccinelli
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* 
 * File:   main.cpp
 * Author: lpiccinelli
 *
 * Created on 3 agosto 2010, 21.34
 */

#include <cstdlib>
#include <iostream>

#include <boost/any.hpp>

#include <cv.h>
#include <highgui.h>

#include "prj_definitions.h"
#include "pipeline/adv_pipeline_data_structures.h"
#include "pipeline/pipeline_data_structures.h"
#include "pipeline/pipeline_io.h"
#include "generators/genericGenerator.h"
#include "imgops/filters/GaussBlurOp.h"
#include "generators/resource/CvImgDirectoryGenerator.h"
#include "generators/bridgeGenerator.h"
#include "imgops/skin/SkinTrainNBayesOp.h"
#include "formatters/cvMat_formatters.h"
#include "formatters/ml_formatters.h"

using namespace std;
using namespace cv;
using namespace NAMESPACE;


class IsOpen{
public:
    CvImgDirectoryGenerator* g;
    int i;

    bool operator()() const{ return g->is_opened(); }
};

int main(int argc, char** argv) {
    string imgs_path;
    string masks_path;

    imgs_path = argv[1];
    masks_path = argv[2];

    NormalBayesModel* model = new Discret2DNormalBayesModel(0, 0, 255, 255);

    // Operations
    SkinTrainNBayesOp skin_train;
    // skin_train input
    CvImgDirectoryGenerator* imgsGenerator  = new CvImgDirectoryGenerator(imgs_path,  skin_train.getInputKeysList().at(0));
    imgsGenerator->set_max_buffer_mem(5000000);
    CvImgDirectoryGenerator* masksGenerator = new CvImgDirectoryGenerator(masks_path, skin_train.getInputKeysList().at(1));
    masksGenerator->set_max_buffer_mem(5000000);
    // skin_train output
    HandledIOElement model_io(model, skin_train.getOutputKeysList().at(0));
    // skin_train criteria
    CVT_SPACE cvt_space = YCRCB;
    HandledIOElement cvt_space_io(&cvt_space, skin_train.getCriteriaKeysList().at(0));
    bool update_skin_model = true;
    HandledIOElement update_skin_model_io(&update_skin_model, skin_train.getCriteriaKeysList().at(1));
    // -------------------------------------------------------------------------

    // ****** Output formatters ************************************************
    BayesHgWndFormatter model_formatter(skin_train.getOutputKeysList().at(0));
    // -------------------------------------------------------------------------

    IsOpen is_open;
    is_open.g = imgsGenerator;

    // ****** Skin train Pipestep **********************************************
    LoopPipeStep<IsOpen> skin_train_step;
    skin_train_step.set_condition(is_open);
    skin_train_step.set_computation(&skin_train);
    skin_train_step.add_input_generator(imgsGenerator)   // Input
                   .add_input_generator(masksGenerator);
    skin_train_step.add_criteria(&cvt_space_io)          // Criteria
                   .add_criteria(&update_skin_model_io);
    skin_train_step.add_output(&model_io);               // Output

    skin_train_step.add_output_formatter(&model_formatter);
    // -------------------------------------------------------------------------

    
    // Operations
    GaussBlurD2DNBayesOp gauss_blur;
    // Gauss Blur input
    HandledIOElement gauss_model_input_io(model, gauss_blur.getInputKeysList().at(0));
    // Gauss Blur output
    HandledIOElement gauss_model_output_io(model, gauss_blur.getOutputKeysList().at(0));
    // gauss blur criteria
    NumericIOElement width(3, gauss_blur.getCriteriaKeysList().at(0));
    NumericIOElement height(3,gauss_blur.getCriteriaKeysList().at(1));
    NumericIOElement sigmaX(1.0, gauss_blur.getCriteriaKeysList().at(2));
    // -------------------------------------------------------------------------

    // ****** Output formatters ************************************************
    BayesXMLFormatter model_xml_formatter(gauss_blur.getOutputKeysList().at(0), "bayesD2D.xml.gz");
    BayesImgFileFormatter model_img_formatter(gauss_blur.getOutputKeysList().at(0), "bayesD2D");
    // -------------------------------------------------------------------------

    // ****** Gauss blur Pipestep **********************************************
    PipeStep gauss_blur_step;
    gauss_blur_step.set_computation(&gauss_blur);
    gauss_blur_step.add_input(&gauss_model_input_io);   // Input
    gauss_blur_step.add_criteria(&width)                // Criteria
                   .add_criteria(&height)
                   .add_criteria(&sigmaX);
    gauss_blur_step.add_output(&gauss_model_output_io); // Output

    gauss_blur_step.add_output_formatter(&model_xml_formatter);
    gauss_blur_step.add_output_formatter(&model_img_formatter);
    // -------------------------------------------------------------------------


    // Pipeline
    Pipeline main_pipe;
    main_pipe.add_pipe_step(&skin_train_step);
    main_pipe.add_pipe_step(&gauss_blur_step);

    // Step of pipeline looping
    PipeStep main_step;
    main_step.set_computation(&main_pipe);

    imgsGenerator->open();
    masksGenerator->open();

    main_step.execute();

    // ****** free resources ***************************************************
    delete imgsGenerator;
    delete masksGenerator;

    delete model;
    // -------------------------------------------------------------------------

    return 0;
}